package com.fanshuai.stack;

import java.util.Iterator;

public class ArrayStack<E> implements Stack<E>, Iterable<E> {
    private E[] array;
    private int capacity;
    private int top;

    private static final int DEFAULT_CAPACITY = 10;
    private static final int SIZE_LIMIT = 4 * 1024 * 1024;

    public ArrayStack() {
        array = (E[]) new Object[DEFAULT_CAPACITY];
        capacity = DEFAULT_CAPACITY;
        top = 0;
    }

    @Override
    public int size() {
        return top;
    }

    @Override
    public boolean isEmpty() {
        return top == 0;
    }

    private int calcSize() {
        if (capacity * 2 < SIZE_LIMIT) {
            return capacity * 2;
        } else {
            return capacity + SIZE_LIMIT;
        }
    }

    private void resize() {
        int newCapacity = calcSize();
        E[] newArray = (E[]) new Object[newCapacity];

        System.arraycopy(array, 0, newArray, 0, top);
        array = newArray;
        capacity = newCapacity;
    }

    @Override
    public void push(E e) {
        if (top == capacity) {
            resize();
        }

        array[top++] = e;
    }

    @Override
    public E pop() {
        if (top <= 0) {
            throw new IndexOutOfBoundsException("stack empty");
        }

        top--;
        E e = array[top];
        array[top] = null;
        return e;
    }

    @Override
    public E peek() {
        if (top <= 0) {
            throw new IndexOutOfBoundsException("stack empty");
        }

        return array[top - 1];
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int index = 0;

            @Override
            public boolean hasNext() {
                return index < top;
            }

            @Override
            public E next() {
                return array[index++];
            }
        };
    }
}
